﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using H2.Streams;

namespace Mystery
{
    public class NetgameFlag
    {
        public const int Size = 32;
        public const int Offset = 280;

        public float PositionX;
        public float PositionY;
        public float PositionZ;

        public float FacingDegrees;

        public short Type;
        public enum TypeEnum
        {
            FlagSpawn = 0,
            FlagReturn = 1,

            BombSpawn = 2,
            BombReturn = 3,

            OddballSpawn = 4,

            TeleporterSource = 7,
            TeleporterDestination = 8,

            TerritoriesFlag = 10,

            KingHill0 = 11,
            KingHill1 = 12,
            KingHill2 = 13,
            KingHill3 = 14,
            KingHill4 = 15,
            KingHill5 = 16,
            KingHill6 = 17,
            KingHill7 = 18,
        }

        public short TeamDesignator;
        public enum TeamDesignatorEnum
        {
            Red = 0,
            Blue = 1,
            Yellow = 2,
            Green = 3,
            Purple = 4,
            Orange = 5,
            Brown = 6,
            Pink = 7,
            Neutral = 8,
        }

        public short Identifier;

        public short Flags;
        public enum FlagsEnum
        {
            None = 0,
            MultipleFlagBomb = 1,
            SingleFlagBomb = 2,
            NeutralFlagBomb = 4,
        }

        public byte[] Padding = new byte[8];

        public void ReadFrom(MapStream stream)
        {
            PositionX = stream.ReadFloat();
            PositionY = stream.ReadFloat();
            PositionZ = stream.ReadFloat();

            FacingDegrees = stream.ReadFloat();

            Type = stream.ReadInt16();
            TeamDesignator = stream.ReadInt16();
            Identifier = stream.ReadInt16();
            Flags = stream.ReadInt16();

            Padding = stream.ReadBytes(Padding.Length);
        }

        public void WriteTo(BaseStream stream)
        {
            stream.Write(PositionX);
            stream.Write(PositionY);
            stream.Write(PositionZ);

            stream.Write(FacingDegrees);

            stream.Write(Type);
            stream.Write(TeamDesignator);
            stream.Write(Identifier);
            stream.Write(Flags);

            stream.Write(Padding);
        }

        static NetgameFlag.TypeEnum[] TeamBaseNetgameGameFlagTypes = new NetgameFlag.TypeEnum[] { TypeEnum.TerritoriesFlag, TypeEnum.FlagSpawn, TypeEnum.FlagReturn, TypeEnum.BombSpawn, TypeEnum.BombReturn };
        static NetgameFlag.TypeEnum[] NeutralBaseNetgameGameFlagTypes = new NetgameFlag.TypeEnum[] { TypeEnum.OddballSpawn, TypeEnum.OddballSpawn, TypeEnum.OddballSpawn, TypeEnum.TerritoriesFlag, TypeEnum.FlagSpawn, TypeEnum.BombSpawn };

        public static int Generate(Scenario scnr, AISquad[] aiSquads, bool addFlagBasePlacements, int flagBaseIndex)
        {
            int hillCount = 0;
            int baseCount = 0;
            foreach (AISquad ais in aiSquads)
            {
                if (ais.NetgameBaseTeam >= 0 && ais.StartingLocations.Length > 0)
                {
                    GenerateBase(scnr, ais.StartingLocations[0], (short)ais.NetgameBaseTeam, addFlagBasePlacements, flagBaseIndex);
                    baseCount++;
                }

                if (ais.NetgameHill)
                {
                    GenerateHill(scnr, ais, hillCount++);
                }
            }
            return baseCount;
        }

        private static void GenerateBase(Scenario scnr, AISquad.StartingLocation sl, short teamIndex, bool addFlagBasePlacements, int flagBaseIndex)
        {
            NetgameFlag.TypeEnum[] types = (teamIndex == 8) ? NeutralBaseNetgameGameFlagTypes : TeamBaseNetgameGameFlagTypes;
            for (int flagIndex = 0; flagIndex < types.Length; flagIndex++)
            {
                NetgameFlag flag = new NetgameFlag();
                flag.PositionX = sl.PositionX;
                flag.PositionY = sl.PositionY;
                flag.PositionZ = sl.PositionZ;
                flag.FacingDegrees = sl.RotationYaw;

                flag.TeamDesignator = teamIndex;
                flag.Type = (short)types[flagIndex];

                if(teamIndex == 8)
                    flag.Flags = (short)(FlagsEnum.MultipleFlagBomb | FlagsEnum.SingleFlagBomb);
                else
                    flag.Flags = (short)(FlagsEnum.NeutralFlagBomb);
                switch (types[flagIndex])
                {
                    case TypeEnum.OddballSpawn:
                        flag.Identifier = (short)flagIndex;
                        break;
                    case TypeEnum.TerritoriesFlag:
                        flag.TeamDesignator = 8;
                        flag.Identifier = teamIndex;
                        break;
                    default:
                        flag.Identifier = 0;
                        break;
                }

                

                scnr.NetgameFlags.Add(flag);
            }

            if (addFlagBasePlacements)
            {
                Scenery flagBase = new Scenery();
                flagBase.PositionX = sl.PositionX;
                flagBase.PositionY = sl.PositionY;
                flagBase.PositionZ = sl.PositionZ;
                flagBase.TypeIndex = (short)flagBaseIndex;
                flagBase.NameIndex = -1;
                flagBase.Source = 1;
                flagBase.Type = 6;//Scenery Type
                flagBase.EditorFolder = -1;
                flagBase.UniqueID = 0xFFFFFFFF;
                flagBase.ValidMultiplayerGames = (ushort)(1 | ((teamIndex == 8) ? 4 : 0) | 32 | 64);

                scnr.Scenery.Add(flagBase);
            }
        }

        private static void GenerateHill(Scenario scnr, AISquad squad, int hillNumber)
        {
            if (hillNumber > 7) return;
            TypeEnum flagType = TypeEnum.KingHill0 + hillNumber;
            for (int i = 0; i < squad.StartingLocations.Length; i++)
            {
                NetgameFlag flag = new NetgameFlag();
                flag.PositionX = squad.StartingLocations[i].PositionX;
                flag.PositionY = squad.StartingLocations[i].PositionY;
                flag.PositionZ = squad.StartingLocations[i].PositionZ;
                flag.FacingDegrees = squad.StartingLocations[i].RotationYaw;

                flag.TeamDesignator = 8;
                flag.Type = (short)flagType;

                flag.Flags = 0;
                flag.Identifier = 0;

                scnr.NetgameFlags.Add(flag);
            }
        }
    }
}
